#include "LecteurPhraseSimple.h"

#include <stdlib.h>
#include <iostream>
using namespace std;

////////////////////////////////////////////////////////////////////////////////
LecteurPhraseSimple::LecteurPhraseSimple(string nomFich) :
	ls(nomFich) {
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::analyse() {
	programme();
	cout << "Syntaxe correcte." << endl;
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::programme() {
// <programme> ::= debut <seqInst> fin FIN_FICHIER
	
	sauterSymCour("debut");
	seqInst();
	sauterSymCour("fin");
	testerSymCour("<FINDEFICHIER>");
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::seqInst() {
// <seqInst> ::= <inst> ; { <inst> ; }

	do {
		inst();
		sauterSymCour(";");
	} while (ls.getSymCour()=="<VARIABLE>" || ls.getSymCour()=="si"
                || ls.getSymCour()=="tantque" || ls.getSymCour()=="repeter"
                || ls.getSymCour()=="pour");
	// tant que le symbole courant est un debut possible d'instruction...
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::affectation() {
// <affectation> ::= <variable> = <expression>

	sauterSymCour("<VARIABLE>");
	sauterSymCour("=");
	expression();
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::expression() {
// <expression> ::= <terme> { <opAdd> <terme> }

	terme();
	while (ls.getSymCour()=="+" || ls.getSymCour()=="-") {
		opAdd();
		terme();
	}
}

////////////////////////////////////////////////////////////////////////////////


 void LecteurPhraseSimple::relation()    
 // <relation> ::= <expression> { <opRel> <expression> }
 {
     expression();
     while (ls.getSymCour()=="==" 
             || ls.getSymCour()=="!=" 
             || ls.getSymCour()=="<" 
             || ls.getSymCour()=="<=" 
             || ls.getSymCour()==">" 
             || ls.getSymCour()==">=")
     {
         opRel();
         expression();
     }
 }

 ////////////////////////////////////////////////////////////////////////////////

void LecteurPhraseSimple::expBool()
// <expBool> ::= <concatenation> { ou <concatenation> }
{
    concatenation();
    while (ls.getSymCour() == "ou")
    {
        ls.suivant();
        concatenation();
    }
}

 ////////////////////////////////////////////////////////////////////////////////

void LecteurPhraseSimple::concatenation()
// <concatenation> ::= <relation> { et <relation> }
{
    relation();
    while (ls.getSymCour() == "et")
    {
        ls.suivant();
        relation();
    }
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::terme()     
// <terme> ::= <facteur> { <opMult> <facteur>} 
{
    facteur();
    while (ls.getSymCour()=="*" || ls.getSymCour()=="/")
    {
        opMult();
        facteur();
    }
    
    
}
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::facteur() {
// <facteur> ::= <entier>  |  <variable> | <opUnaire> <expBool> | ( <expBool> )

	if (ls.getSymCour()=="<VARIABLE>" || ls.getSymCour()=="<ENTIER>")
		ls.suivant();

        else if (ls.getSymCour()=="(") 
        {
		ls.suivant();
		expBool();
		sauterSymCour(")");
	} 
        else if (ls.getSymCour()=="-" || ls.getSymCour()=="non")
        {
            opUnaire();
            expBool();
        }
        else
		erreur("<facteur>");
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::opAdd()
// <opAdd> ::= + | -
{
	if (ls.getSymCour()=="+" || ls.getSymCour()=="-")
		ls.suivant();
	else
		erreur("<opAdd>");
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::opMult()
// <opMult> ::= * | /
{
	if (ls.getSymCour()=="*" || ls.getSymCour()=="/")
		ls.suivant();
	else
		erreur("<opMult>");
}

 ////////////////////////////////////////////////////////////////////////////////

void LecteurPhraseSimple::opRel()
// <opRel> ::= == | != | < | <= | > | >=
{
    if (ls.getSymCour()=="==" 
             || ls.getSymCour()=="!=" 
             || ls.getSymCour()=="<" 
             || ls.getSymCour()=="<=" 
             || ls.getSymCour()==">" 
             || ls.getSymCour()==">=")
        ls.suivant();
    else
        erreur("<opRel>");
}
////////////////////////////////////////////////////////////////////////////////

void LecteurPhraseSimple::opUnaire()
// <opUnaire> ::= -|non
{
    if(ls.getSymCour()=="-" || ls.getSymCour()=="non")
        ls.suivant();
    else
        erreur("<opUnaire>");
}
 ////////////////////////////////////////////////////////////////////////////////
    void LecteurPhraseSimple::inst()        
    // <inst> ::= <affectation> | <instSi> | <instTq> | <instRepeter>
    {
        if (ls.getSymCour()=="<VARIABLE>") {
            affectation();
        }
        else if (ls.getSymCour()=="si") {
            instSi();
        }
        else if (ls.getSymCour()=="tantque") {
            instTq();
        }
        else if (ls.getSymCour()=="repeter") {
            instRepeter();
        }
        else {
            erreur("<inst1>");
        }
    }
////////////////////////////////////////////////////////////////////////////////
    void LecteurPhraseSimple::instSi()      
  //<instSi> ::= si ( <expBool> ) <seqInst> { sinonsi ( <expBool> ) <seqInst> } [ sinon <seqInst> ] finsi
    {
        sauterSymCour("si");
        sauterSymCour("(");
        expBool();
        sauterSymCour(")");
        seqInst();
        while (ls.getSymCour()=="sinonsi") {
            ls.suivant();
            sauterSymCour("(");
            expBool();
            sauterSymCour(")");
            seqInst();
        }
        if (ls.getSymCour()=="sinon") {
            ls.suivant();
            seqInst();
        }
        sauterSymCour("finsi");
    }
////////////////////////////////////////////////////////////////////////////////
    void LecteurPhraseSimple::instTq()
    //<instTq> ::= tantque ( <expBool> ) <seqInst> fintantque
    {
        sauterSymCour("tantque");
        sauterSymCour("(");
        expBool();
        sauterSymCour(")");
        seqInst();
        sauterSymCour("fintantque");
    }
////////////////////////////////////////////////////////////////////////////////
    void LecteurPhraseSimple::instRepeter()
    //<instRepeter> ::= repeter <seqInst> jusqua ( <expBool> )
    {
        sauterSymCour("repeter");
        seqInst();
        sauterSymCour("jusqua");
        sauterSymCour("(");
        expBool();
        sauterSymCour(")");
    }
    
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::instLire()    
// <instLire> ::= lire ( <variable> )
{
    sauterSymCour("lire");
    sauterSymCour("(");
    sauterSymCour("<VARIABLE");
    sauterSymCour(")");
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::instEcrire()  
// <instEcrire> ::= ecrire ( <expression> | <chaine> )
{
    sauterSymCour("ecrire");
    sauterSymCour("(");
    if (ls.getSymCour()=="<CHAINE>" ) {
        ls.suivant();
    }
    else if (ls.getSymCour()=="<ENTIER>" || ls.getSymCour()=="<VARIABLE>"
            || ls.getSymCour()=="-" || ls.getSymCour()=="non" 
            || ls.getSymCour()=="(" ) {
        ls.suivant();
    }
    else {
        erreur("<instEcrire>");
    }
}
////////////////////////////////////////////////////////////////////////////////

void LecteurPhraseSimple::instPour()
 //<instPour> ::= pour ( <affectation> ; <expression> ; <affectation> ) <seqInst> finpour
{
    sauterSymCour("pour");
    sauterSymCour("(");
    affectation();
    sauterSymCour(";");
    expression();
    sauterSymCour(";");
    affectation();
    sauterSymCour(")");
    seqInst();
    sauterSymCour("finpour");
}

//////////////////////////////////////////////////////////////////////////////// 
void LecteurPhraseSimple::testerSymCour(string ch) {
	if (ls.getSymCour() != ch) {
		cout << endl << "-------- Erreur ligne " << ls.getLigne()
				<< " - Colonne " << ls.getColonne() << endl << "   Attendu : "
				<< ch << endl << "   Trouve  : " << ls.getSymCour() << endl
				<< endl;
		exit(0); // plus tard, on levera une exception
	}
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::sauterSymCour(string ch) {
	testerSymCour(ch);
	ls.suivant();
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::erreur(string mess) {
	cout << endl << "-------- Erreur ligne " << ls.getLigne() << " - Colonne "
			<< ls.getColonne() << endl << "   Attendu : " << mess << endl
			<< "   Trouve  : " << ls.getSymCour() << endl << endl;
	exit(0); // plus tard, on levera une exception
}